package com.seamtop.cuber.client;

import com.seamtop.cuber.common.base.DataObject;
import com.seamtop.cuber.common.entriy.*;
import com.seamtop.cuber.common.exception.CuberParamsProcessException;
import com.seamtop.cuber.common.metadata.RowKey;
import com.seamtop.cuber.common.metadata.TableMetaData;
import com.seamtop.cuber.common.util.ParamsUtil;

import java.util.HashMap;

/**
 * Created by feng on 2015/8/8.
 * �ͻ���API�ӿ�
 */
public enum  CuberClient {

    INSTANCE;

    //��������
    private IOperator operater;

    private CuberClient (){
        CuberOperatorProxy proxy = new CuberOperatorProxy();
        operater = (IOperator)proxy.bind(new RealityOperator());
    }

    public <T extends Object> void addIndex(String tableName,HashMap<String,T> paramsMap) throws Exception{
        HashMap<String,TableMetaData> metaDataHashMap = DataObject.getMetaDataMap();
        TableMetaData tableMetaData = metaDataHashMap.get(tableName);
        if(tableMetaData == null || tableMetaData.isVirtualTable() || tableMetaData.isResultTable()){
            throw new CuberParamsProcessException(new ErrorCode(ErrorCode.TABLE_ISNOT_EXIST,tableName).toString());
        }
        CuberMessage message = new CuberMessage();
        message.setMsgType("ADD_"+tableName);
        message.setMsgData(paramsMap);
        operater.execute(message);
    }


    public <T extends Object> void updateIndex(String tableName,HashMap<String,T> paramsMap) throws Exception{
        HashMap<String,TableMetaData> metaDataHashMap = DataObject.getMetaDataMap();
        TableMetaData tableMetaData = metaDataHashMap.get(tableName);
        if(tableMetaData == null || tableMetaData.isVirtualTable() || tableMetaData.isResultTable()){
            throw new CuberParamsProcessException(new ErrorCode(ErrorCode.TABLE_ISNOT_EXIST,tableName).toString());
        }
        CuberMessage message = new CuberMessage();
        message.setMsgType("UPDATE_"+tableName);
        message.setMsgData(paramsMap);
        operater.execute(message);
    }

    public <T extends Object> void deleteIndex(String tableName,T key) throws Exception{
        HashMap<String,TableMetaData> metaDataHashMap = DataObject.getMetaDataMap();
        TableMetaData tableMetaData = metaDataHashMap.get(tableName);
        if(tableMetaData == null || tableMetaData.isVirtualTable() || tableMetaData.isResultTable()){
            throw new CuberParamsProcessException(new ErrorCode(ErrorCode.TABLE_ISNOT_EXIST,tableName).toString());
        }
        RowKey rowKey = tableMetaData.getRowKey();
        String tableKeyName = rowKey.getKeyName();
        CuberMessage message = new CuberMessage();
        HashMap<String,T> paramsMap = new HashMap<String, T>();
        paramsMap.put(tableKeyName,key);
        message.setMsgType("DELETE_"+tableName);
        message.setMsgData(paramsMap);
        operater.execute(message);
    }

    /**
     * @param tableName
     * @param paramsMap
     * @param
     * @throws Exception
     */
    public <T extends Object> void statIncrement(String tableName,HashMap<String,T> paramsMap) throws Exception{
        HashMap<String,TableMetaData> metaDataHashMap = DataObject.getMetaDataMap();
        TableMetaData tableMetaData = metaDataHashMap.get(tableName);
        if(tableMetaData == null || tableMetaData.isResultTable() || !tableMetaData.isVirtualTable()){
            throw new CuberParamsProcessException(new ErrorCode(ErrorCode.TABLE_ISNOT_EXIST,tableName).toString());
        }
        if(ParamsUtil.isMapEmpty(paramsMap)){
            throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_IS_NULL).toString());
        }
        CuberMessage message = new CuberMessage();
        message.setMsgType("INCREMENT_"+tableName);
        message.setMsgData(paramsMap);
        operater.execute(message);


    }


    /**
     * params#price,value#10-15��
     * @param tableName
     * @param kvMap
     * @param paramsMap
     * @throws Exception
     */
    public <T extends Object> void statIncrement(String tableName,HashMap<String,T> kvMap,HashMap<String,T> paramsMap) throws Exception{
        HashMap<String,TableMetaData> metaDataHashMap = DataObject.getMetaDataMap();
        TableMetaData tableMetaData = metaDataHashMap.get(tableName);
        if(tableMetaData == null || tableMetaData.isResultTable() || !tableMetaData.isVirtualTable()){
            throw new CuberParamsProcessException(new ErrorCode(ErrorCode.TABLE_ISNOT_EXIST,tableName).toString());
        }
        if(ParamsUtil.isMapEmpty(kvMap)){
            throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_IS_NULL).toString());
        }

        if(paramsMap == null){
            paramsMap = new HashMap<String, T>();
        }
        for(String key : kvMap.keySet()){
            String tempKey = key;
            String tempValue = (String)kvMap.get(key);
            if(tempKey.indexOf(CuberContants.CUBER_COMPLEX_SPLIT) == -1 || tempValue.indexOf(CuberContants.CUBER_COMPLEX_SPLIT) == -1){
                throw new CuberParamsProcessException(new ErrorCode(ErrorCode.PARAMS_IS_NULL).toString());
            }
            paramsMap.put(tempKey.split(CuberContants.CUBER_COMPLEX_SPLIT)[0],(T)tempKey.split(CuberContants.CUBER_COMPLEX_SPLIT)[1]);
            paramsMap.put(tempValue.split(CuberContants.CUBER_COMPLEX_SPLIT)[0],(T)tempValue.split(CuberContants.CUBER_COMPLEX_SPLIT)[1]);
            CuberMessage message = new CuberMessage();
            message.setMsgType("INCREMENT_"+tableName);
            message.setMsgData(paramsMap);
            operater.execute(message);
        }
    }


    public <T extends Number> void statIncrement(String counterName,T increase) throws Exception{
        HashMap<String,CuberCounter> cuberCounterMap = DataObject.getCuberCounterMap();
        CuberCounter cuberCounter = cuberCounterMap.get(counterName);
        if(cuberCounter == null){
            throw new CuberParamsProcessException(new ErrorCode(ErrorCode.COUNTER_ISNOT_EXIST,counterName).toString());
        }
        HashMap<String,Object> paramsMap = new HashMap<String, Object>();
        paramsMap.put("value",(int)(increase.doubleValue() * 1000));
        CuberMessage message = new CuberMessage();
        message.setMsgType("INCREMENT_" + counterName);
        message.setMsgData(paramsMap);
        operater.execute(message);
    }
}
